package org.m8.auth.handler.social;

import cn.hutool.core.util.RandomUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.m8.auth.handler.AbstractAuthLoginHandler;
import org.m8.auth.handler.AuthLoginHandlerRegistry;
import org.m8.auth.controller.vo.AuthLoginRespVO;
import org.m8.auth.model.SocialUserBindDO;
import org.m8.auth.model.SocialUserBindService;
import org.m8.user.model.User;
import org.m8.user.model.UserService;
import org.m8.util.JsonUtil;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Map;

import static org.m8.util.exception.ServiceExceptionUtil.exception;
import static org.m8.util.exception.emnus.GlobalErrorCodeConstants.AUTH_SOCIAL_USER_NOT_FOUND;

/**
 * 社交登录
 *
 * @author yidanjun
 * @date 2024/9/7
 **/
@Slf4j
@Service
public class SocialAuthLoginHandler extends AbstractAuthLoginHandler {

    private static final String AUTH_LOGIN_TYPE = "social";
    @Resource
    private SocialUserBindService socialUserBindService;

    @Resource
    private UserService userService;

    @Override
    protected void init() {
        AuthLoginHandlerRegistry.getInstance().register(AUTH_LOGIN_TYPE, this);
    }

    @Override
    public < R extends AuthLoginRespVO> R login(Map<String, Object> req) {
        SocialAuthSocialLoginReqVO socialAuthSocialLoginReqVO = JsonUtil.parse(req, SocialAuthSocialLoginReqVO.class);
        // 普通的社交登录
        return (R)socialLogin(socialAuthSocialLoginReqVO.getSocialType(), socialAuthSocialLoginReqVO.getCode(), socialAuthSocialLoginReqVO.getState());
    }


    /**
     * 登录
     *
     * @param socialType
     * @param code
     * @param state
     * @return
     */
    private SocialAuthLoginRespVO socialLogin(String socialType, String code, String state) {
        SocialUserBindDO socialUserBindDO = socialUserBindService.authSocialUser(socialType, code, state, null);

        if (socialUserBindDO == null) {
            throw exception(AUTH_SOCIAL_USER_NOT_FOUND);
        }

        User userDto;
        if (socialUserBindDO.getUserId() != null){
            userDto = userService.getUser(socialUserBindDO.getUserId());
        } else {
            userDto = new User();
            userDto.setUsername("w_" + RandomUtil.randomString(10));
            userDto.setName(userDto.getUsername());
            userService.addUser(userDto);

            socialUserBindDO.setUserId(userDto.getUsername());
            socialUserBindDO.setUpdateTime(new Date());
            socialUserBindService.bindUser(socialUserBindDO);
        }

        return createTokenAfterLoginSuccess(userDto, socialUserBindDO);
    }

}
